from typing import Union
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware  # 导入 CORSMiddleware
from fastapi.openapi.models import Response
from pydantic import BaseModel
from markitdown import MarkItDown
from fastapi import FastAPI, File, UploadFile
from typing import Annotated
import uvicorn
from fastapi.staticfiles import StaticFiles
import os
from openai import OpenAI
import json
from fastapi.responses import HTMLResponse

app = FastAPI()

origins = [
    "http://localhost:5173",
    "http://localhost:8000",  # 添加你允许访问的域名和端口
    # 可以添加更多允许的 origins
]

app.add_middleware(
    CORSMiddleware,
    allow_origins=origins,
    allow_credentials=True,
    allow_methods=["*"],  # 允许所有方法，如 GET, POST, PUT, DELETE
    allow_headers=["*"],  # 允许所有头部
)


# app.mount("/static", StaticFiles(directory="static"), name="static")

# client = OpenAI(
#     # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key="sk-xxx",
#     api_key="",  # 如何获取API Key：https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key
#     base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
# )


class Item(BaseModel):
    name: str
    price: float
    is_offer: Union[bool, None] = None


# @app.get("/")
# def read_root():
#     return {"Hello": "World"}


# @app.get("/items/{item_id}")
# def read_item(item_id: int, q: Union[str, None] = None):
#     return {"item_id": item_id, "q": q}


# @app.put("/items/{item_id}")
# def update_item(item_id: int, item: Item):
#     return {"item_name": item.name, "item_id": item_id}


# @app.post("/files/")
# async def create_file(file: Annotated[bytes, File()]):
#     md = MarkItDown(enable_plugins=False)  # Set to True to enable plugins
#     result = md.convert(file)
# print()
# return result.text_content


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile):
    # 检查文件扩展名
    filename = file.filename.lower()
    if not (filename.endswith('.xlsx') or filename.endswith('.docx')
            or filename.endswith('.jpg')):
        return {
            "error": "只支持Excel(.xlsx)和Word(.docx)、.jpg 文件格式"
        }

    # 获取当前目录路径
    current_dir = os.getcwd()
    # 拼接文件保存路径 
    file_path = os.path.join(current_dir + "/static", file.filename)

    # 读取文件内容并写入到目标路径
    contents = await file.read()
    with open(file_path, "wb") as f:
        f.write(contents)

    # 使用 MarkItDown 转换文件为 markdown
    if (filename.endswith('.jpg')):
        print(1)
    else:
        md = MarkItDown()
        result = md.convert(file_path)

    # 删除临时保存的文件
    os.remove(file_path)

    return {
        "filename": file.filename,
        "markdown_content": result.text_content
    }


def generate_api_markdown(postman_data):
    markdown = f"# {postman_data.get('name', '接口文档')}\n\n"

    for i, request in enumerate(postman_data.get('requests', [])):
        # 添加API标题和编号
        markdown += f"## {i + 1}.{request.get('name', '未命名接口')}\n\n"

        # 添加请求方法
        markdown += f"**方法**: {request.get('method', '')}\n\n"

        # 添加请求端点
        markdown += f"**端点**: `{request.get('endpoint', '')}`\n\n"

        # 添加请求参数(如果有)
        if request.get('params') and len(request['params']) > 0:
            markdown += "### 请求参数\n\n"

            # 参数表格形式
            params_table = []
            for param in request['params']:
                if param.get('active', False):
                    params_table.append(
                        f"| {param.get('key', '')} | {param.get('value', '')} | {param.get('description', '')} |")

            if params_table:
                markdown += "| 参数名 | 值 | 描述 |\n"
                markdown += "| ------ | --- | ---- |\n"
                markdown += "\n".join(params_table) + "\n\n"

        # 添加请求头
        if request.get('headers') and len(request['headers']) > 0:
            markdown += "### 请求头\n\n"

            # 请求头表格形式
            headers_table = []
            for header in request['headers']:
                if header.get('active', False):
                    headers_table.append(f"| {header.get('key', '')} | {header.get('value', '')} |")

            if headers_table:
                markdown += "| 键 | 值 |\n"
                markdown += "| --- | --- |\n"
                markdown += "\n".join(headers_table) + "\n\n"

        # 添加请求体
        if request.get('body') and request['body'].get('body'):
            body_content = request['body']['body']
            if body_content and body_content.strip():
                markdown += "### 请求体\n\n"

                # 代码块中显示请求体，带行号效果
                try:
                    # 处理可能存在的转义字符，确保JSON正确解析
                    body_content = body_content.replace('\\n', '\n').replace('\\r', '\r').replace('\\t', '\t')
                    body_json = json.loads(body_content)
                    pretty_body = json.dumps(body_json, indent=2, ensure_ascii=False)
                    # 添加行号
                    lines = pretty_body.split('\n')
                    numbered_lines = []
                    for j, line in enumerate(lines):
                        numbered_lines.append(f" {line}")

                    markdown += "```json\n" + "\n".join(numbered_lines) + "\n```\n\n"
                except json.JSONDecodeError:
                    # 如果不是有效的JSON，则原样显示
                    # 处理可能存在的转义字符
                    body_content = body_content.replace('\\n', '\n').replace('\\r', '\r').replace('\\t', '\t')
                    lines = body_content.split('\n')
                    numbered_lines = []
                    for j, line in enumerate(lines):
                        numbered_lines.append(f" {line}")

                    markdown += "```json\n" + "\n".join(numbered_lines) + "\n```\n\n"

        # 添加响应部分标题
        markdown += "### 响应\n\n"
        markdown += "```json\n {\n     \"code\": \"0\",\n     \"errMsg\": \"success\",\n     \"data\": null\n }\n```\n\n"

        # 添加分隔符
        markdown += "---\n\n"

    return markdown


@app.post("/convert-postman-to-markdown/")
async def convert_postman_to_markdown(file: UploadFile):
    """上传Postman JSON文件并转换为Markdown文档"""
    # 检查文件扩展名
    filename = file.filename.lower()
    if not filename.endswith('.json'):
        return {
            "error": "只支持Postman导出的JSON文件"
        }

    # 读取文件内容
    contents = await file.read()
    try:
        postman_data = json.loads(contents)
        # 生成Markdown文档
        markdown = generate_api_markdown(postman_data)

        # 处理转义字符
        markdown = markdown.replace('\\n', '\n').replace('\\r', '\r').replace('\\t', '\t')

        return {
            "markdown_content": markdown
        }
    except json.JSONDecodeError:
        return {
            "error": "无效的JSON文件"
        }


@app.get("/parse-local-postman/", response_class=HTMLResponse)
async def parse_local_postman():
    """解析本地的Postman文件并生成Markdown文档"""
    try:
        # 读取当前目录下的workspace.postman_globals.json文件
        current_dir = os.getcwd()
        postman_file = os.path.join(current_dir, "workspace.postman_globals.json")

        if not os.path.exists(postman_file):
            return {"error": "未找到workspace.postman_globals.json文件"}

        with open(postman_file, "r", encoding="utf-8") as f:
            postman_data = json.load(f)

        # 生成Markdown文档
        markdown = generate_api_markdown(postman_data)

        # 返回可视化的HTML页面
        html_content = f"""
        <!DOCTYPE html>
        <html>
        <head>
            <title>{postman_data.get('name', '接口文档')}</title>
            <meta charset="UTF-8">
            <style>
                body {{ font-family: Arial, sans-serif; max-width: 900px; margin: 0 auto; padding: 20px; }}
                h1 {{ color: #333; }}
                h2 {{ color: #333; margin-top: 30px; background-color: #f5f5f5; padding: 10px; }}
                code {{ background-color: #f5f5f5; padding: 2px 4px; }}
                pre {{ background-color: #f5f5f5; padding: 15px; border-radius: 5px; overflow-x: auto; }}
                table {{ border-collapse: collapse; width: 100%; }}
                th, td {{ text-align: left; padding: 8px; border: 1px solid #ddd; }}
                tr:nth-child(even) {{ background-color: #f2f2f2; }}
                .code-block {{ background-color: #f0f0f0; padding: 10px; border-radius: 5px; overflow-x: auto; line-height: 1.5; }}
                .line-number {{ color: #999; display: inline-block; width: 20px; text-align: right; padding-right: 10px; }}
            </style>
        </head>
        <body>
            <div id="markdown-content">
                {markdown.replace('```', '<pre class="code-block">').replace('```', '</pre>')}
            </div>
        </body>
        </html>
        """
        return html_content

    except Exception as e:
        return {
            "error": f"解析Postman文件出错: {str(e)}"
        }


def save_markdown_to_file(output_file="api_docs.md"):
    """将Postman文件转换为Markdown并保存到文件"""
    try:
        # 读取当前目录下的workspace.postman_globals.json文件
        current_dir = os.getcwd()
        postman_file = os.path.join(current_dir, "workspace.postman_globals.json")

        if not os.path.exists(postman_file):
            print(f"错误: 未找到文件 {postman_file}")
            return False

        with open(postman_file, "r", encoding="utf-8") as f:
            postman_data = json.load(f)

        # 生成Markdown文档
        markdown = generate_api_markdown(postman_data)

        # 移除任何剩余的转义字符
        markdown = markdown.replace('\\n', '\n').replace('\\r', '\r').replace('\\t', '\t')

        # 保存到文件
        with open(output_file, "w", encoding="utf-8") as f:
            f.write(markdown)

        print(f"文档已成功保存到 {output_file}")
        return True
    except Exception as e:
        print(f"生成文档时出错: {str(e)}")
        return False


if __name__ == "__main__":
    import sys

    # 如果有命令行参数，则直接生成文档
    if len(sys.argv) > 1 and sys.argv[1] == "--generate-docs":
        output_file = "api_docs.md"
        if len(sys.argv) > 2:
            output_file = sys.argv[2]
        save_markdown_to_file(output_file)
    else:
        # 否则启动服务器
        uvicorn.run(app, host="0.0.0.0", port=8000)
